<template>
  <div id="app">
    <div id="map" style="width: 100%; height: 500px;"></div>

    <div class="control-panel">
      <button @click="showAddDialog = true">添加标注</button>
      <button @click="generatePath">生成路径</button>
      <button @click="clearMap">清除所有</button>

    </div>
    <router-link to="/home">
      <button>前往首页</button>
    </router-link>
    <router-view></router-view>

    <!-- 添加标注对话框 -->
    <div v-if="showAddDialog" class="dialog-mask">
      <div class="dialog-content">
        <h3>添加新标注点</h3>
        <div class="form-group">
          <label>经度：</label>
          <input v-model="newMarker.lng" type="number" step="0.000001">
        </div>
        <div class="form-group">
          <label>纬度：</label>
          <input v-model="newMarker.lat" type="number" step="0.000001">
        </div>
        <div class="form-group">
          <label>图片URL：</label>
          <input v-model="newMarker.image">
        </div>
        <div class="form-group">
          <label>描述：</label>
          <textarea v-model="newMarker.description"></textarea>
        </div>
        <div class="dialog-buttons">
          <button @click="confirmAdd">确认</button>
          <button @click="cancelAdd">取消</button>
        </div>
      </div>
    </div>

    <!-- 加载提示 -->
    <div v-if="loading" class="loading-mask">
      <div class="loading-text">路径计算中，请稍候...</div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'BaiduMap',
  data() {
    return {
      map: null,
      markers: [],
      polyline: null,
      overlayList: [],
      infoWindow: null,
      showAddDialog: false,
      loading: false,
      newMarker: {
        lng: 110.937882,
        lat: 23.380321,
        image: '',
        description: ''
      }
    };
  },
  mounted() {
    this.initMap();
    this.loadMarkers();
  },
  methods: {
    initMap() {
      this.map = new BMapGL.Map("map");
      this.map.centerAndZoom(new BMapGL.Point(110.937882, 23.380321), 19);
      this.map.enableScrollWheelZoom(true);

      this.map.addControl(new BMapGL.ScaleControl({anchor: BMAP_ANCHOR_TOP_LEFT}));
      this.map.addControl(new BMapGL.NavigationControl());

      this.infoWindow = new BMapGL.InfoWindow("", {
        width: 400,
        height: 'auto'
      });
    },

    async loadMarkers() {
      const saved = localStorage.getItem("mapMarkers");
      if (saved) {
        try {
          this.markers = JSON.parse(saved);
          this.markers.forEach(marker => this.createMapMarker(marker));
        } catch(e) {
          console.error("加载标注点失败:", e);
        }
      }
    },

    createMapMarker(markerData) {
      const point = new BMapGL.Point(markerData.lng, markerData.lat);
      const marker = new BMapGL.Marker(point);

      marker.customData = {
        image: markerData.image,
        description: markerData.description
      };

      marker.addEventListener("click", () => this.showInfoWindow(marker, point));
      this.map.addOverlay(marker);
      this.overlayList.push(marker);
    },

    showInfoWindow(marker, point) {
      const content = `
        <div class="info-content">
          ${marker.customData.image ? `
            <div class="image-box">
              <img src="${marker.customData.image}"
                   style="width:100%;height:auto;max-height:200px;object-fit:cover;"
                   onerror="this.style.display='none'"
                   alt="标注点图片">
            </div>
          ` : ''}
          <div class="info-text">
            <h4>坐标信息</h4>
            <p>经度：${point.lng.toFixed(6)}</p>
            <p>纬度：${point.lat.toFixed(6)}</p>
            ${marker.customData.description ? `
              <div class="description">
                <h4>描述</h4>
                <p>${marker.customData.description}</p>
              </div>
            ` : ''}
          </div>
          <button class="delete-btn">删除此点</button>
        </div>
      `;

      this.infoWindow.setContent(content);
      this.map.openInfoWindow(this.infoWindow, point);

      setTimeout(() => {
        document.querySelector(".delete-btn")?.addEventListener("click", () => {
          this.deleteMarker(marker);
          this.map.closeInfoWindow();
        });
      }, 50);
    },

    async generatePath() {
      if (this.markers.length < 2) {
        alert("至少需要两个标注点！");
        return;
      }
      if (this.markers.length > 10) {
        if (!confirm("标注点较多可能导致计算缓慢，确认继续吗？")) return;
      }

      this.loading = true;
      try {
        await this.forceUpdatePath();
      } finally {
        this.loading = false;
      }
    },

    async forceUpdatePath() {
      this.clearPolylines();

      if (this.markers.length >= 2) {
        const path = await this.calculateOptimalPath();
        if (path.length > 1) {
          this.polyline = new BMapGL.Polyline(path, {
            strokeColor: "#FF4040",
            strokeWeight: 3,
            strokeOpacity: 0.8
          });
          this.map.addOverlay(this.polyline);
          this.overlayList.push(this.polyline);
        }
      }
    },

    async calculateOptimalPath() {
      try {
        const { next } = await this.generateFloydPaths();
        return this.buildOptimalPath(next);
      } catch(e) {
        console.error("路径计算失败:", e);
        return [];
      }
    },

    generateFloydPaths() {
      return new Promise((resolve) => {
        const points = this.markers.map(m => new BMapGL.Point(m.lng, m.lat));
        const n = points.length;
        const dist = Array(n).fill().map(() => Array(n).fill(Infinity));
        const next = Array(n).fill().map(() => Array(n).fill(-1));

        // 初始化距离矩阵
        for (let i = 0; i < n; i++) {
          for (let j = 0; j < n; j++) {
            if (i === j) {
              dist[i][j] = 0;
            } else {
              dist[i][j] = this.map.getDistance(points[i], points[j]);
              next[i][j] = j;
            }
          }
        }

        // Floyd算法核心
        for (let k = 0; k < n; k++) {
          for (let i = 0; i < n; i++) {
            for (let j = 0; j < n; j++) {
              if (dist[i][j] > dist[i][k] + dist[k][j]) {
                dist[i][j] = dist[i][k] + dist[k][j];
                next[i][j] = next[i][k];
              }
            }
          }
        }

        resolve({ dist, next });
      });
    },

    buildOptimalPath(next) {
      const points = this.markers.map(m => new BMapGL.Point(m.lng, m.lat));
      let bestPath = [];
      let shortestLength = Infinity;

      // 从每个点出发寻找最优路径
      for (let start = 0; start < points.length; start++) {
        const path = [];
        let current = start;
        const visited = new Set();

        while (true) {
          path.push(points[current]);
          visited.add(current);

          let nextNode = -1;
          let minDist = Infinity;
          for (let i = 0; i < points.length; i++) {
            if (!visited.has(i) && next[current][i] !== -1) {
              const dist = this.map.getDistance(points[current], points[i]);
              if (dist < minDist) {
                minDist = dist;
                nextNode = i;
              }
            }
          }

          if (nextNode === -1) break;
          current = nextNode;
        }

        const pathLength = this.calculatePathLength(path);
        if (pathLength < shortestLength) {
          shortestLength = pathLength;
          bestPath = path;
        }
      }

      return bestPath;
    },

    calculatePathLength(path) {
      return path.reduce((total, point, index) => {
        if (index > 0) {
          return total + this.map.getDistance(path[index-1], point);
        }
        return total;
      }, 0);
    },

    deleteMarker(marker) {
      const pos = marker.getPosition();
      this.map.removeOverlay(marker);

      this.overlayList = this.overlayList.filter(overlay =>
          !(overlay instanceof BMapGL.Marker &&
              overlay.getPosition().lng === pos.lng &&
              overlay.getPosition().lat === pos.lat)
      );

      this.markers = this.markers.filter(m =>
          m.lng !== pos.lng || m.lat !== pos.lat
      );

      this.saveMarkers();
      this.forceUpdatePath();
    },

    confirmAdd() {
      if (!this.validateCoord()) {
        alert("请输入有效的经纬度！");
        return;
      }

      const newMarker = {
        lng: parseFloat(this.newMarker.lng),
        lat: parseFloat(this.newMarker.lat),
        image: this.newMarker.image,
        description: this.newMarker.description
      };

      this.markers.push(newMarker);
      this.createMapMarker(newMarker);
      this.saveMarkers();
      this.forceUpdatePath();
      this.cancelAdd();
    },

    validateCoord() {
      return !isNaN(this.newMarker.lng) &&
          !isNaN(this.newMarker.lat) &&
          this.newMarker.lng >= -180 &&
          this.newMarker.lng <= 180 &&
          this.newMarker.lat >= -90 &&
          this.newMarker.lat <= 90;
    },

    cancelAdd() {
      this.showAddDialog = false;
      this.resetForm();
    },

    resetForm() {
      this.newMarker = {
        lng: 110.937882,
        lat: 23.380321,
        image: '',
        description: ''
      };
    },

    saveMarkers() {
      localStorage.setItem("mapMarkers", JSON.stringify(this.markers));
    },

    clearPolylines() {
      this.overlayList
          .filter(overlay => overlay instanceof BMapGL.Polyline)
          .forEach(line => this.map.removeOverlay(line));
      this.overlayList = this.overlayList.filter(
          overlay => !(overlay instanceof BMapGL.Polyline)
      );
    },

    clearMap() {
      this.clearPolylines();
      this.overlayList.forEach(overlay => this.map.removeOverlay(overlay));
      this.overlayList = [];
      this.markers = [];
      localStorage.removeItem("mapMarkers");
    }
  }
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  position: relative;
  height: 100vh;
}

.control-panel {
  position: absolute;
  top: 20px;
  left: 20px;
  z-index: 1000;
  background: rgba(255,255,255,0.9);
  padding: 15px;
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0,0,0,0.1);
}

button {
  margin: 5px;
  padding: 8px 15px;
  background: #409EFF;
  border: none;
  border-radius: 4px;
  color: white;
  cursor: pointer;
  transition: all 0.3s;
}

button:hover {
  background: #66b1ff;
  transform: translateY(-1px);
}

.dialog-mask {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0,0,0,0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 2000;
  overflow: auto;
}

.dialog-content {
  background: white;
  padding: 25px;
  border-radius: 10px;
  width: 400px;
  box-shadow: 0 2px 20px rgba(0,0,0,0.2);
}

.form-group {
  margin: 15px 0;
}

.form-group label {
  display: block;
  margin-bottom: 8px;
  font-weight: 500;
  color: #606266;
}

.form-group input,
.form-group textarea {
  width: 100%;
  padding: 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.info-content {
  width: 380px !important;
  max-height: 60vh;
  overflow-y: auto;
}

.image-box img {
  width: 100%;
  height: 200px;
  object-fit: cover;
  border-radius: 4px;
}

.loading-mask {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(255,255,255,0.8);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 3000;
}

.loading-text {
  font-size: 1.2em;
  color: #409EFF;
  padding: 20px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0,0,0,0.1);
}
</style>


//这是第二条测试提交